﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace PTA
{
    /// <summary>
    /// 提供正则验证功能.
    /// </summary>
    public static class Regular
    {
        /// <summary>
        /// 从输入字符串中的第一个字符开始，用替换字符串替换指定的正则表达式模式的所有匹配项。
        /// </summary>
        /// <param name="pattern">模式字符串</param>
        /// <param name="input">输入字符串</param>
        /// <param name="evaluator">找到每个正则表达式时调用的方法</param>
        /// <param name="options">正则表达式找到匹配项</param>
        /// <returns>返回被替换后的结果</returns>
        public static string Replace(string value, string pattern, MatchEvaluator evaluator, RegexOptions options = RegexOptions.None)
        {
            return Regex.Replace(value, pattern, evaluator, options);
        }

        /// <summary>
        /// 从输入字符串中的第一个字符开始，用替换字符串替换指定的正则表达式模式的所有匹配项。
        /// </summary>
        /// <param name="pattern">模式字符串</param>
        /// <param name="input">输入字符串</param>
        /// <param name="replacement">用于替换的字符串</param>
        /// <param name="options">正则表达式找到匹配项</param>
        /// <returns>返回被替换后的结果</returns>
        public static string Replace(string value, string pattern, string replacement, RegexOptions options)
        {
            return Regex.Replace(value, pattern, replacement, options);
        }

        /// <summary>
        /// 在由正则表达式模式定义的位置拆分输入字符串。
        /// </summary>
        /// <param name="pattern">模式字符串</param>
        /// <param name="input">输入字符串</param>
        /// <param name="options">正则表达式选项</param>
        /// <returns>分割后的字符串数组</returns>
        public static string[] Split(string value, string pattern, RegexOptions options)
        {
            return Regex.Split(value, pattern, options);
        }

        /// <summary>
        /// 获取匹配字符串
        /// </summary>
        /// <param name="pattern">模式字符串</param>
        /// <param name="input">输入字符串</param>
        /// <param name="options"></param>
        /// <returns></returns>
        public static MatchCollection Matches(string value, string pattern, RegexOptions options)
        {
            return Regex.Matches(value, pattern, options);
        }

        #region 验证字符串是否满足指定的类型
        /// <summary>
        /// 验证字符串是否满足指定的类型
        /// </summary>
        /// <param name="value">要验证的字符串</param>
        /// <param name="type">验证类型</param>
        /// <param name="enableNullOrEmpty">要验证的内容是否允许为null或string.Empty</param>
        /// <returns>返回一个值，指示传入的参数是否是指定的类型</returns>
        public static bool CheckString(string value, ValidateType type, bool enableNullOrEmpty = true)
        {
            bool result = false;
            if (enableNullOrEmpty && string.IsNullOrEmpty(value))
            {
                result = true;
            }
            if (type == ValidateType.NullOrWhiteSpace)
            {
                result = string.IsNullOrWhiteSpace(value);
            }
            else
            {
                #region 主体验证部分
                if (value == null || value.Length == 0)
                {
                    return result;
                }
                switch (type)
                {
                    case ValidateType.Int:
                        {
                            int temp;
                            result = int.TryParse(value, out temp);
                            break;
                        }
                    case ValidateType.GreaterThanZeroInt:
                        {
                            int temp;
                            if (int.TryParse(value, out temp))
                            {
                                result = temp > 0;
                            }
                            break;
                        }
                    case ValidateType.LessThanZeroInt:
                        {
                            int temp;
                            if (int.TryParse(value, out temp))
                            {
                                result = temp < 0;
                            }
                            break;
                        }
                    case ValidateType.Long:
                        {
                            int temp;
                            result = int.TryParse(value, out temp);
                            break;
                        }
                    case ValidateType.GreaterThanZeroLong:
                        {
                            long temp;
                            if (long.TryParse(value, out temp))
                            {
                                result = temp > 0;
                            }
                            break;
                        }
                    case ValidateType.LessThanZeroLong:
                        {
                            long temp;
                            if (long.TryParse(value, out temp))
                            {
                                result = temp < 0;
                            }
                            break;
                        }
                    case ValidateType.Float:
                        {
                            float temp;
                            result = float.TryParse(value, out temp);
                            break;
                        }
                    case ValidateType.GreaterThanZeroFloat:
                        {
                            float temp;
                            if (float.TryParse(value, out temp))
                            {
                                result = temp > 0;
                            }
                            break;
                        }
                    case ValidateType.LessThanZeroFloat:
                        {
                            float temp;
                            if (float.TryParse(value, out temp))
                            {
                                result = temp < 0;
                            }
                            break;
                        }
                    case ValidateType.Double:
                        {
                            double temp;
                            result = double.TryParse(value, out temp);
                            break;
                        }
                    case ValidateType.GreaterThanZeroDouble:
                        {
                            double temp;
                            if (double.TryParse(value, out temp))
                            {
                                result = temp > 0;
                            }
                            break;
                        }
                    case ValidateType.LessThanZeroDouble:
                        {
                            double temp;
                            if (double.TryParse(value, out temp))
                            {
                                result = temp < 0;
                            }
                            break;
                        }
                    default:
                        {
                            string pattern = typeof(Regular).GetField("RegExp" + type.ToString(), System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public).GetValue(null).ToString();
                            result = Regex.IsMatch(value, pattern);
                            break;
                        }
                }
                #endregion
            }
            return result;
        }

        public static bool CheckString(string value, string pattern, bool enableNullOrEmpty = true, RegexOptions options = RegexOptions.None)
        {
            bool result = false;
            if (enableNullOrEmpty && string.IsNullOrEmpty(value))
            {
                result = true;
            }
            result = Regex.IsMatch(value, pattern, options);
            return true;
        }
        #endregion

        #region 正则验证表达式
        public const string RegExpChinaMobile = @"^1(3[4-9]|5[012789]|8[78])\d{8}$"; //中国移动：134.135.136.137.138.139.150.151.152.157.158.159.187.188 ,147(数据卡)
        public const string RegExpChinaUnicom = @"^1(3[0-2]|5[56]|8[56])\d{8}$"; //中国联通：130.131.132.155.156.185.186
        public const string RegExpChinaTelcom = @"^1(8[09]|[35]3)\d{8}$"; //中国电信：133.153.180.189 
        public const string RegExpFixedPhone = @"^0(10|2[0-9]|[3-9][0-9]{2})-?\d{7,8}(-\d+)?$"; //固定电话
        public const string RegExpMobile = @"^1((47)|(3[0-9])|(5[012356789])(8[056789])[0-9]8$"; //中国手机号码
        public const string RegExpEmail = @"^[_\.0-9a-zA-Z-]+@([0-9a-zA-Z][0-9a-zA-Z-]+\.)+[a-zA-Z]{2,3}$"; //邮箱
        public const string RegExpChineseChar = @"^[\u4e00-\u9fa5]+$";//汉字
        public const string RegExpEnglishChar = @"^[a-zA-Z]+$";//英文字符，大小写
        public const string RegExpEnglishCharUnderlineNumber = @"^[a-zA-Z0-9_]+$"; //英文数字下划线
        public const string RegExpEnglishCharUnderline_EnglishCharUnderlineNumber = @"^[a-zA-Z_]+[a-zA-Z0-9_]+$"; //以英文或下划线开头的只包含英文数字下划线的字符串
        public const string RegExpIPAddress = @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$";//IP地址
        public const string RegExpDate = @"^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-))$";//日期
        public const string RegExpTime = @"^(20|21|22|23|[0-1]?\d):[0-5]?\d:[0-5]?\d$";//时间
        public const string RegExpDateTime = @"^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-)) (20|21|22|23|[0-1]?\d):[0-5]?\d:[0-5]?\d$";//日期时间
        public const string RegExpHtml = "<(S*?)[^>]*>.*?|<.*? />"; //HTML
        public const string RegExpUserId = "^[a-zA-Z][a-zA-Z0-9_]{5,19}$ ";//用户ID号，字母开头，允许6-20字符，允许字母数字下划线
        public const string RegExpIdentityCard = @"^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$"; //身份证号码
        public const string RegExpQQ = @"^[1-9][0-9]{4,9}$"; //QQ号码
        public const string RegExpNumberJoin = @"^(\d+|,)+$";//用逗号分隔的数字
        public const string RegExpStrictNumberJoin = @"^\d+(,\d+)*$";//严格的用逗号分隔的数字
        public const string RegExpStringJoin = @"^(\w+|,)+$";//用逗号分隔的字符串
        public const string RegExpStrictStringJoin = @"^\w+(,\w+)*$"; //严格的用逗号分隔的字符串
        public const string RegExpGuid = @"^[a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12}$"; //GUID
        #endregion
    }
    /// <summary>
    /// 正则表达式验证的类型
    /// </summary>
    public enum ValidateType
    {
        /// <summary>
        /// 不验证
        /// </summary>
        None,
        /// <summary>
        /// 空字符串或全部为空格的字符串
        /// </summary>
        NullOrWhiteSpace,

        /// <summary>
        /// 整数
        /// </summary>
        Int,

        /// <summary>
        /// 大于0整数
        /// </summary>
        GreaterThanZeroInt,

        /// <summary>
        /// 小于0整数
        /// </summary>
        LessThanZeroInt,

        /// <summary>
        /// 长整数
        /// </summary>
        Long,

        /// <summary>
        /// 大于0整数
        /// </summary>
        GreaterThanZeroLong,

        /// <summary>
        /// 小于0整数
        /// </summary>
        LessThanZeroLong,

        /// <summary>
        /// 浮点型
        /// </summary>
        Float,

        /// <summary>
        /// 大于0浮点型
        /// </summary>
        GreaterThanZeroFloat,

        /// <summary>
        /// 小于0浮点型
        /// </summary>
        LessThanZeroFloat,

        /// <summary>
        /// 双精度数
        /// </summary>
        Double,

        /// <summary>
        /// 大于0双精度数
        /// </summary>
        GreaterThanZeroDouble,

        /// <summary>
        /// 小于0双精度数
        /// </summary>
        LessThanZeroDouble,

        /// <summary>
        /// 电子邮箱
        /// </summary>
        Email,

        /// <summary>
        /// HTML
        /// </summary>
        Html,

        /// <summary>
        /// 汉字
        /// </summary>
        ChineseChar,

        /// <summary>
        /// 英文
        /// </summary>
        EnglishChar,

        /// <summary>
        /// 英文下划线数字
        /// </summary>
        EnglishCharUnderlineNumber,

        /// <summary>
        /// 英文下划线数字且以英文或下划线开头
        /// </summary>
        EnglishCharUnderline_EnglishCharUnderlineNumber,

        /// <summary>
        /// 手机号
        /// </summary>
        Mobile,

        /// <summary>
        /// 中国移动电话
        /// </summary>
        ChinaMobile,

        /// <summary>
        /// 中国联通电话
        /// </summary>
        ChinaUnicom,

        /// <summary>
        /// 中国电信电话
        /// </summary>
        ChinaTelcom,

        /// <summary>
        /// 固定电话
        /// </summary>
        FixedPhone,

        /// <summary>
        /// 字母开头，允许6-20字节，允许字母数字下划线
        /// </summary>
        UserId,

        /// <summary>
        /// 18位身份证号码
        /// </summary>
        IdentityCard,

        /// <summary>
        /// QQ号码
        /// </summary>
        QQ,

        /// <summary>
        /// 验证IP地址
        /// </summary>
        IPAddress,

        /// <summary>
        /// 日期验证(yyyy-MM-dd)
        /// </summary>
        Date,

        /// <summary>
        /// 时间验证(HH:mm:ss)
        /// </summary>
        Time,

        /// <summary>
        /// 日期时间(yyyy-MM-dd HH:mm:dd) 
        /// </summary>
        DateTime,

        /// <summary>
        /// 验证GUID
        /// </summary>
        Guid,

        /// <summary>
        /// 数字连接串(连接符为',',有可能只是连接符号的组合,而没有数字)
        /// </summary>
        NumberJoin,

        /// <summary>
        /// 严格数字连接串(要求必须为如:x或者x,x,x,x的样式,连接符为',')
        /// </summary>
        StrictNumberJoin,

        /// <summary>
        /// 字符串连接串(连接符为',',有可能只是连接符号的组合,而没有字符)
        /// </summary>
        StringJoin,

        /// <summary>
        /// 严格字符串连接串(要求必须为如:x或者x,x,x,x的样式,连接符为',')
        /// </summary>
        StrictStringJoin
    }

}
